#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#define BMP280_U32_t unsigned long
#define BMP280_S32_t long
#define BMP280_S64_t long long
// Temperature compensation
#define dig_T1 ((unsigned short) 27294)
#define dig_T2 ((short) 26669)
#define dig_T3 ((short)-1000)

// Pressure compensation
#define dig_P1 ((unsigned short) 37288)
#define dig_P2 ((short)-10578)
#define dig_P3 ((short) 3024)
#define dig_P4 ((short) 5452)
#define dig_P5 ((short)  188)
#define dig_P6 ((short)   -7)
#define dig_P7 ((short)15500)
#define dig_P8 ((short)-14600)
#define dig_P9 ((short) 6000)


// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.  
// t_fine carries fine temperature as global value 
BMP280_S32_t t_fine; 
BMP280_S32_t bmp280_compensate_T_int32(BMP280_S32_t adc_T) 
{ 
BMP280_S32_t var1, var2, T; 
var1  = ((((adc_T>>3) - ((BMP280_S32_t)dig_T1<<1))) * ((BMP280_S32_t)dig_T2)) >> 11; 
var2  = (((((adc_T>>4) - ((BMP280_S32_t)dig_T1)) * ((adc_T>>4) - ((BMP280_S32_t)dig_T1))) >> 12) *  
((BMP280_S32_t)dig_T3)) >> 14; 
t_fine = var1 + var2; 
T  = (t_fine * 5 + 128) >> 8; 
return T; 
} 
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). 
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa 
BMP280_U32_t bmp280_compensate_P_int64(BMP280_S32_t adc_P) 
{ 
BMP280_S64_t var1, var2, p; 
var1 = ((BMP280_S64_t)t_fine) - 128000; 
var2 = var1 * var1 * (BMP280_S64_t)dig_P6; 
var2 = var2 + ((var1*(BMP280_S64_t)dig_P5)<<17); 
var2 = var2 + (((BMP280_S64_t)dig_P4)<<35); 
var1 = ((var1 * var1 * (BMP280_S64_t)dig_P3)>>8) + ((var1 * (BMP280_S64_t)dig_P2)<<12); 
var1 = (((((BMP280_S64_t)1)<<47)+var1))*((BMP280_S64_t)dig_P1)>>33; 
if (var1 == 0) 
{ 
return 0; // avoid exception caused by division by zero 
} 
p = 1048576-adc_P; 
p = (((p<<31)-var2)*3125)/var1; 
var1 = (((BMP280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25; 
var2 = (((BMP280_S64_t)dig_P8) * p) >> 19; 
p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)dig_P7)<<4); 
return (BMP280_U32_t)p;
}

float BMP280_Calculate_Altitude_Temperature(float pressure_pa, float sea_level_pressure_pa, float temperature_c)
{
    const float T0 = temperature_c + 273.15f; // 绝对温度，开尔文
    const float L = 0.0065f;   // 温度递减率，K/m
    const float g = 9.80665f;  // 重力加速度，m/s^2
    const float R = 8.31447f;  // 理想气体常数，J/(mol·K)
    const float M = 0.0289644f; // 干空气摩尔质量，kg/mol

    // 指数计算
    float exponent = (R * L) / (g * M);

    // 计算海拔高度，单位米
    float altitude = (T0 / L) * (powf(pressure_pa / sea_level_pressure_pa, -exponent) - 1.0f);

    return altitude;
}

int main() {
    uint32_t adc_P = 394718;
    uint32_t adc_T = 531376;
    BMP280_S32_t temperature;
    BMP280_U32_t pressure;
    temperature = bmp280_compensate_T_int32(adc_T);
    pressure = bmp280_compensate_P_int64(adc_P)/256; // 转换为 Pa
    float altitude = BMP280_Calculate_Altitude_Temperature(pressure, 101325.0f, temperature / 100.0f); // 海平面压力为 101325 Pa
    printf("Pressure = %lu\n", pressure); 
    printf("altitude = %.2f m\n", altitude);
    printf("Temperature = %.2f C\n", temperature / 100.0f);
    return 0;
}
